﻿using System;
//using System.Windows.Threading;
using System.ComponentModel;
using SharpDX;
using System.IO;
using SharpDX.XAPO;
using System.Runtime.InteropServices;
using SynergyLib.DSP;


namespace XAudio2Controls
{
    [StructLayout(LayoutKind.Sequential)]
    public struct GraphingParam
    {

    }

    public class GraphingEffect : AudioProcessorBase<GraphingParam>, ISpectrumPlayer
    {
        #region Fields
        int fftDataSize = (int)FFTDataSize.FFT2048;
        DataStream activeStream;
        SampleAggregator sampleAggregator;
        private bool isPlaying = true;
        private int _counter;
        #endregion

        #region Properties
        public bool IsPlaying
        {
            get
            { return isPlaying; }
            set
            { isPlaying = value; NotifyPropertyChanged("IsPlaying"); }
        }

        public DataStream ActiveStream
        {
            get { return activeStream; }
            set
            {
                activeStream = value;
                NotifyPropertyChanged("ActiveStream");
            }
        }

        #endregion

        #region Constructor
        public GraphingEffect()
        {
            sampleAggregator = new SampleAggregator((int)FFTDataSize.FFT2048);

            RegistrationProperties = new RegistrationProperties()
            {
                Clsid = Utilities.GetGuidFromType(typeof(GraphingEffect)),
                CopyrightInfo = "Copyright",
                FriendlyName = "Grapher",
                MaxInputBufferCount = 1,
                MaxOutputBufferCount = 1,
                MinInputBufferCount = 1,
                MinOutputBufferCount = 1,
                Flags = PropertyFlags.Default
            };

        }
        ~GraphingEffect()
        {
            IsPlaying = false;
            if (ActiveStream != null)
                ActiveStream.Dispose();
        }
        #endregion

        public unsafe override void Process(BufferParameters[] inputProcessParameters, BufferParameters[] outputProcessParameters, bool isEnabled)
        {

            int frameCount = inputProcessParameters[0].ValidFrameCount;
            if (ActiveStream == null)
                ActiveStream = new DataStream(inputProcessParameters[0].Buffer, frameCount * InputFormatLocked.BlockAlign, true, true);
            DataStream output = new DataStream(inputProcessParameters[0].Buffer, frameCount * InputFormatLocked.BlockAlign, true, true);
            //ActiveStream.Position = 0;
            
            for (int j = 1; j < frameCount; j++, _counter++)
            {
                //float left = output.Read<float>();
                //float right = output.Read<float>();
                if (j != frameCount)
                {
                    sampleAggregator.Add(output.Read<float>(), output.Read<float>());
                }
                else
                {
                    sampleAggregator.Add(0, 0);
                }
            }
            ActiveStream.Close();
            output.Close();
            this.UnlockForProcess();
        }

        #region IDisposable



        #endregion

        #region ISpectrumPlayer
        public bool GetFFTData(float[] fftDataBuffer)
        {
            sampleAggregator.GetFFTResults(fftDataBuffer);
            return isPlaying;
        }
        public int GetFFTFrequencyIndex(int frequency)
        {
            double maxFrequency;
            if (ActiveStream != null)
                maxFrequency = InputFormatLocked.SampleRate/2.0d;
            else
                maxFrequency = 22050; // Assume a default 44.1 kHz sample rate.
            return (int)((frequency / maxFrequency) * (fftDataSize / 2));
        }
        #endregion

        #region EventHandlers

        #endregion

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(null, new PropertyChangedEventArgs(info));
            }
        }
        #endregion


    }
}

